#include "sys/socket.h"
#include "netinet/in.h"
#include "errno.h"
#include "stdio.h"

#define BUFSIZE 50

void udp_server()
{
	int sock;
	struct sockaddr_in server_addr, remote_addr;
	int bind_ret_val, recv_ret_val, send_ret_val;
	char buf[BUFSIZE];
	int sockaddr_len;
	int one = 1;
	int bind_port;

	memset(&server_addr, 0, sizeof(server_addr));
	memset(&remote_addr, 0, sizeof(remote_addr));

	sockaddr_len = sizeof(struct sockaddr);

	sock = socket(PF_INET, SOCK_DGRAM, 0);
	if(-1 == sock) {
		printf("&udp_server: fail to create a socket, program exit.\n");
		printf("&udp_server: the failure reason is %d.\n", errno);
		exit(0);
	}


	server_addr.sin_family = AF_INET;
	printf("plz enter the port to bind the udp server:\n");
	scanf("%d", &bind_port);
	server_addr.sin_port = htons(bind_port);
	server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

	if(-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
			&one, sizeof(one))) {
		printf("&udp_server: fail to setsockopt, program exit.\n");
		printf("&udp_server: the failure reason is %d.\n", errno);
		exit(0);
	}

	bind_ret_val = bind(sock, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
	if(-1 == bind_ret_val) {
		printf("&udp_server: fail to bind, program exit.\n");
		printf("&udp_server: the failure reason is %d.\n", errno);
		exit(0);
	}

	while(1) {
		memset(buf, 0, BUFSIZE);
		recv_ret_val = recvfrom(sock, buf, BUFSIZE, 0,
				(struct sockaddr*)&remote_addr, &sockaddr_len);
		if(-1 == recv_ret_val) {
			printf("&udp_server: fail to reveive messages from remote, program exit.\n");
			printf("&udp_server: the failure reason is %d.\n", errno);
			exit(0);
		}
		else if(0 == recv_ret_val) {
			printf("&udp_server: the remote address is %s\n", inet_ntoa(remote_addr.sin_addr));
			printf("&udp_server: the remote port is %d\n", ntohs(remote_addr.sin_port));
			printf("&udp_server: remote device shutdown.\n");
		}
		else {
			buf[recv_ret_val] = '\0';
			printf("&udp_server: the remote address is %s\n", inet_ntoa(remote_addr.sin_addr));
			printf("&udp_server: the remote port is %d\n", ntohs(remote_addr.sin_port));
			printf("&udp_server: the message reveived from remote is %s\n", buf);
			send_ret_val = sendto(sock, "received by server.", strlen("received by server."), 0,
					(struct sockaddr*)&remote_addr, sizeof(struct sockaddr));
			if(-1 == send_ret_val) {
				printf("&udp_server: fail to send message to remote, program exit.\n");
				printf("&udp_server: the failure reason is %d.\n", errno);
				exit(0);
			}
		}
	}

	close(sock);

	return;
}
